#include "No7pch.h"
#include "OpenGLVertexArray.h"

#include <glad/glad.h>

NAMESPACE_BEGIN
static GLenum shaderDataTypeToOpenGLBaseType(nmspc::ShaderDataType type)
{
	switch (type)
	{
	case Core::ShaderDataType::Float:   return GL_FLOAT;
	case Core::ShaderDataType::Float2:  return GL_FLOAT;
	case Core::ShaderDataType::Float3:  return GL_FLOAT;
	case Core::ShaderDataType::Float4:  return GL_FLOAT;
	case Core::ShaderDataType::Mat3:    return GL_FLOAT;
	case Core::ShaderDataType::Mat4:    return GL_FLOAT;
	case Core::ShaderDataType::Int:     return GL_INT;
	case Core::ShaderDataType::Int2:    return GL_INT;
	case Core::ShaderDataType::Int3:    return GL_INT;
	case Core::ShaderDataType::Int4:    return GL_INT;
	case Core::ShaderDataType::Bool:    return GL_BOOL;
	}
	NO7_CORE_ASSERT(false, "Unknown ShaderDataType!");
	return 0;
}
NAMESPACE_END

nmspc::OpenGLVertexArray::OpenGLVertexArray()
{
	glCreateVertexArrays(1, &this->vertex_array_id);
}

nmspc::OpenGLVertexArray::~OpenGLVertexArray()
{
	glDeleteVertexArrays(1, &this->vertex_array_id);
}

void nmspc::OpenGLVertexArray::bind() const
{
	glBindVertexArray(this->vertex_array_id);
}

void nmspc::OpenGLVertexArray::unBind() const
{
	glBindVertexArray(0);
}

void nmspc::OpenGLVertexArray::addVertexBuffer(const std::shared_ptr<nmspc::VertexBuffer>& vertex_buffer)
{
	NO7_CORE_ASSERT(vertex_buffer->getLayout().getElements().size(), "Vertex buffer has no layout!");
	glBindVertexArray(this->vertex_array_id);
	vertex_buffer->bind();
	std::uint32_t index = 0;
	const auto& layout = vertex_buffer->getLayout();
	for (const auto& element : layout)
	{
		glEnableVertexAttribArray(index);
		glVertexAttribPointer(
			index,
			element.getComponentCount(),
			shaderDataTypeToOpenGLBaseType(element.type),
			element.normalized ? GL_TRUE : GL_FALSE,
			layout.getStride(),
			(const void*)element.offset
		);
		index++;
	}
	this->vertex_buffers.push_back(vertex_buffer);
}

void nmspc::OpenGLVertexArray::setIndexBuffer(const std::shared_ptr<nmspc::IndexBuffer>& index_buffer)
{
	glBindVertexArray(this->vertex_array_id);
	index_buffer->bind();
	this->index_buffer = index_buffer;
}
